﻿// Type: System.Windows.Forms.TreeNode
// Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Windows.Forms.dll

using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;

namespace System.Windows.Forms
{
  [DefaultProperty("Text")]
  [TypeConverter(typeof (TreeNodeConverter))]
  [Serializable]
  public class TreeNode : MarshalByRefObject, ICloneable, ISerializable
  {
    private static readonly int insertMask = 35;
    private string toolTipText = "";
    private const int SHIFTVAL = 12;
    private const int CHECKED = 8192;
    private const int UNCHECKED = 4096;
    private const int ALLOWEDIMAGES = 14;
    internal const int MAX_TREENODES_OPS = 200;
    private const int TREENODESTATE_isChecked = 1;
    internal OwnerDrawPropertyBag propBag;
    internal IntPtr handle;
    internal string text;
    internal string name;
    private BitVector32 treeNodeState;
    private TreeNode.TreeNodeImageIndexer imageIndexer;
    private TreeNode.TreeNodeImageIndexer selectedImageIndexer;
    private TreeNode.TreeNodeImageIndexer stateImageIndexer;
    private ContextMenu contextMenu;
    private ContextMenuStrip contextMenuStrip;
    internal bool nodesCleared;
    internal int index;
    internal int childCount;
    internal TreeNode[] children;
    internal TreeNode parent;
    internal TreeView treeView;
    private bool expandOnRealization;
    private bool collapseOnRealization;
    private TreeNodeCollection nodes;
    private object userData;

    internal TreeNode.TreeNodeImageIndexer ImageIndexer
    {
      get
      {
        if (this.imageIndexer == null)
          this.imageIndexer = new TreeNode.TreeNodeImageIndexer(this, TreeNode.TreeNodeImageIndexer.ImageListType.Default);
        return this.imageIndexer;
      }
    }

    internal TreeNode.TreeNodeImageIndexer SelectedImageIndexer
    {
      get
      {
        if (this.selectedImageIndexer == null)
          this.selectedImageIndexer = new TreeNode.TreeNodeImageIndexer(this, TreeNode.TreeNodeImageIndexer.ImageListType.Default);
        return this.selectedImageIndexer;
      }
    }

    internal TreeNode.TreeNodeImageIndexer StateImageIndexer
    {
      get
      {
        if (this.stateImageIndexer == null)
          this.stateImageIndexer = new TreeNode.TreeNodeImageIndexer(this, TreeNode.TreeNodeImageIndexer.ImageListType.State);
        return this.stateImageIndexer;
      }
    }

    [SRDescription("TreeNodeBackColorDescr")]
    [SRCategory("CatAppearance")]
    public Color BackColor
    {
      get
      {
        if (this.propBag == null)
          return Color.Empty;
        else
          return this.propBag.BackColor;
      }
      set
      {
        Color backColor = this.BackColor;
        if (value.IsEmpty)
        {
          if (this.propBag != null)
          {
            this.propBag.BackColor = Color.Empty;
            this.RemovePropBagIfEmpty();
          }
          if (backColor.IsEmpty)
            return;
          this.InvalidateHostTree();
        }
        else
        {
          if (this.propBag == null)
            this.propBag = new OwnerDrawPropertyBag();
          this.propBag.BackColor = value;
          if (value.Equals((object) backColor))
            return;
          this.InvalidateHostTree();
        }
      }
    }

    [Browsable(false)]
    public Rectangle Bounds
    {
      get
      {
        if (this.TreeView == null)
          return Rectangle.Empty;
        System.Windows.Forms.NativeMethods.RECT lParam = new System.Windows.Forms.NativeMethods.RECT();
        *(IntPtr*) &lParam.left = this.Handle;
        if ((int) System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4356, 1, out lParam) == 0)
          return Rectangle.Empty;
        else
          return Rectangle.FromLTRB(lParam.left, lParam.top, lParam.right, lParam.bottom);
      }
    }

    internal Rectangle RowBounds
    {
      get
      {
        System.Windows.Forms.NativeMethods.RECT lParam = new System.Windows.Forms.NativeMethods.RECT();
        *(IntPtr*) &lParam.left = this.Handle;
        if (this.TreeView == null || (int) System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4356, 0, out lParam) == 0)
          return Rectangle.Empty;
        else
          return Rectangle.FromLTRB(lParam.left, lParam.top, lParam.right, lParam.bottom);
      }
    }

    internal bool CheckedStateInternal
    {
      get
      {
        return this.treeNodeState[1];
      }
      set
      {
        this.treeNodeState[1] = value;
      }
    }

    internal bool CheckedInternal
    {
      get
      {
        return this.CheckedStateInternal;
      }
      set
      {
        this.CheckedStateInternal = value;
        if (this.handle == IntPtr.Zero)
          return;
        TreeView treeView = this.TreeView;
        if (treeView == null || !treeView.IsHandleCreated)
          return;
        System.Windows.Forms.NativeMethods.TV_ITEM lParam = new System.Windows.Forms.NativeMethods.TV_ITEM();
        lParam.mask = 24;
        lParam.hItem = this.handle;
        lParam.stateMask = 61440;
        lParam.state |= value ? 8192 : 4096;
        System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) treeView, treeView.Handle), System.Windows.Forms.NativeMethods.TVM_SETITEM, 0, ref lParam);
      }
    }

    [DefaultValue(false)]
    [SRDescription("TreeNodeCheckedDescr")]
    [SRCategory("CatBehavior")]
    public bool Checked
    {
      get
      {
        return this.CheckedInternal;
      }
      set
      {
        TreeView treeView = this.TreeView;
        if (treeView != null)
        {
          if (treeView.TreeViewBeforeCheck(this, TreeViewAction.Unknown))
            return;
          this.CheckedInternal = value;
          treeView.TreeViewAfterCheck(this, TreeViewAction.Unknown);
        }
        else
          this.CheckedInternal = value;
      }
    }

    [SRDescription("ControlContextMenuDescr")]
    [DefaultValue(null)]
    [SRCategory("CatBehavior")]
    public virtual ContextMenu ContextMenu
    {
      get
      {
        return this.contextMenu;
      }
      set
      {
        this.contextMenu = value;
      }
    }

    [DefaultValue(null)]
    [SRCategory("CatBehavior")]
    [SRDescription("ControlContextMenuDescr")]
    public virtual ContextMenuStrip ContextMenuStrip
    {
      get
      {
        return this.contextMenuStrip;
      }
      set
      {
        this.contextMenuStrip = value;
      }
    }

    [Browsable(false)]
    public TreeNode FirstNode
    {
      get
      {
        if (this.childCount == 0)
          return (TreeNode) null;
        else
          return this.children[0];
      }
    }

    TreeNode FirstVisibleParent
    {
      private get
      {
        TreeNode treeNode = this;
        while (treeNode != null && treeNode.Bounds.IsEmpty)
          treeNode = treeNode.Parent;
        return treeNode;
      }
    }

    [SRCategory("CatAppearance")]
    [SRDescription("TreeNodeForeColorDescr")]
    public Color ForeColor
    {
      get
      {
        if (this.propBag == null)
          return Color.Empty;
        else
          return this.propBag.ForeColor;
      }
      set
      {
        Color foreColor = this.ForeColor;
        if (value.IsEmpty)
        {
          if (this.propBag != null)
          {
            this.propBag.ForeColor = Color.Empty;
            this.RemovePropBagIfEmpty();
          }
          if (foreColor.IsEmpty)
            return;
          this.InvalidateHostTree();
        }
        else
        {
          if (this.propBag == null)
            this.propBag = new OwnerDrawPropertyBag();
          this.propBag.ForeColor = value;
          if (value.Equals((object) foreColor))
            return;
          this.InvalidateHostTree();
        }
      }
    }

    [Browsable(false)]
    public string FullPath
    {
      get
      {
        TreeView treeView = this.TreeView;
        if (treeView == null)
          throw new InvalidOperationException(System.Windows.Forms.SR.GetString("TreeNodeNoParent"));
        StringBuilder path = new StringBuilder();
        this.GetFullPath(path, treeView.PathSeparator);
        return ((object) path).ToString();
      }
    }

    [Browsable(false)]
    public IntPtr Handle
    {
      get
      {
        if (this.handle == IntPtr.Zero)
          this.TreeView.CreateControl();
        return this.handle;
      }
    }

    [TypeConverter(typeof (TreeViewImageIndexConverter))]
    [SRCategory("CatBehavior")]
    [RelatedImageList("TreeView.ImageList")]
    [SRDescription("TreeNodeImageIndexDescr")]
    [Localizable(true)]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RefreshProperties(RefreshProperties.Repaint)]
    [DefaultValue(-1)]
    public int ImageIndex
    {
      get
      {
        return this.ImageIndexer.Index;
      }
      set
      {
        this.ImageIndexer.Index = value;
        this.UpdateNode(2);
      }
    }

    [SRDescription("TreeNodeImageKeyDescr")]
    [TypeConverter(typeof (TreeViewImageKeyConverter))]
    [DefaultValue("")]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RefreshProperties(RefreshProperties.Repaint)]
    [RelatedImageList("TreeView.ImageList")]
    [SRCategory("CatBehavior")]
    [Localizable(true)]
    public string ImageKey
    {
      get
      {
        return this.ImageIndexer.Key;
      }
      set
      {
        this.ImageIndexer.Key = value;
        this.UpdateNode(2);
      }
    }

    [SRDescription("TreeNodeIndexDescr")]
    [SRCategory("CatBehavior")]
    public int Index
    {
      get
      {
        return this.index;
      }
    }

    [Browsable(false)]
    public bool IsEditing
    {
      get
      {
        TreeView treeView = this.TreeView;
        if (treeView != null)
          return treeView.editNode == this;
        else
          return false;
      }
    }

    [Browsable(false)]
    public bool IsExpanded
    {
      get
      {
        if (this.handle == IntPtr.Zero)
          return this.expandOnRealization;
        else
          return (this.State & 32) != 0;
      }
    }

    [Browsable(false)]
    public bool IsSelected
    {
      get
      {
        if (this.handle == IntPtr.Zero)
          return false;
        else
          return (this.State & 2) != 0;
      }
    }

    [Browsable(false)]
    public bool IsVisible
    {
      get
      {
        if (this.handle == IntPtr.Zero)
          return false;
        TreeView treeView = this.TreeView;
        System.Windows.Forms.NativeMethods.RECT lParam = new System.Windows.Forms.NativeMethods.RECT();
        *(IntPtr*) &lParam.left = this.Handle;
        bool flag = (int) System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) treeView, treeView.Handle), 4356, 1, out lParam) != 0;
        if (flag)
        {
          Size clientSize = treeView.ClientSize;
          flag = lParam.bottom > 0 && lParam.right > 0 && lParam.top < clientSize.Height && lParam.left < clientSize.Width;
        }
        return flag;
      }
    }

    [Browsable(false)]
    public TreeNode LastNode
    {
      get
      {
        if (this.childCount == 0)
          return (TreeNode) null;
        else
          return this.children[this.childCount - 1];
      }
    }

    [Browsable(false)]
    public int Level
    {
      get
      {
        if (this.Parent == null)
          return 0;
        else
          return this.Parent.Level + 1;
      }
    }

    [Browsable(false)]
    public TreeNode NextNode
    {
      get
      {
        if (this.index + 1 < this.parent.Nodes.Count)
          return this.parent.Nodes[this.index + 1];
        else
          return (TreeNode) null;
      }
    }

    [Browsable(false)]
    public TreeNode NextVisibleNode
    {
      get
      {
        if (this.TreeView == null)
          return (TreeNode) null;
        TreeNode firstVisibleParent = this.FirstVisibleParent;
        if (firstVisibleParent != null)
        {
          IntPtr handle = System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4362, 6, firstVisibleParent.Handle);
          if (handle != IntPtr.Zero)
            return this.TreeView.NodeFromHandle(handle);
        }
        return (TreeNode) null;
      }
    }

    [Localizable(true)]
    [SRCategory("CatAppearance")]
    [SRDescription("TreeNodeNodeFontDescr")]
    [DefaultValue(null)]
    public Font NodeFont
    {
      get
      {
        if (this.propBag == null)
          return (Font) null;
        else
          return this.propBag.Font;
      }
      set
      {
        Font nodeFont = this.NodeFont;
        if (value == null)
        {
          if (this.propBag != null)
          {
            this.propBag.Font = (Font) null;
            this.RemovePropBagIfEmpty();
          }
          if (nodeFont == null)
            return;
          this.InvalidateHostTree();
        }
        else
        {
          if (this.propBag == null)
            this.propBag = new OwnerDrawPropertyBag();
          this.propBag.Font = value;
          if (value.Equals((object) nodeFont))
            return;
          this.InvalidateHostTree();
        }
      }
    }

    [ListBindable(false)]
    [Browsable(false)]
    public TreeNodeCollection Nodes
    {
      get
      {
        if (this.nodes == null)
          this.nodes = new TreeNodeCollection(this);
        return this.nodes;
      }
    }

    [Browsable(false)]
    public TreeNode Parent
    {
      get
      {
        TreeView treeView = this.TreeView;
        if (treeView != null && this.parent == treeView.root)
          return (TreeNode) null;
        else
          return this.parent;
      }
    }

    [Browsable(false)]
    public TreeNode PrevNode
    {
      get
      {
        int num = this.index;
        int fixedIndex = this.parent.Nodes.FixedIndex;
        if (fixedIndex > 0)
          num = fixedIndex;
        if (num > 0 && num <= this.parent.Nodes.Count)
          return this.parent.Nodes[num - 1];
        else
          return (TreeNode) null;
      }
    }

    [Browsable(false)]
    public TreeNode PrevVisibleNode
    {
      get
      {
        TreeNode firstVisibleParent = this.FirstVisibleParent;
        if (firstVisibleParent != null)
        {
          if (this.TreeView == null)
            return (TreeNode) null;
          IntPtr handle = System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4362, 7, firstVisibleParent.Handle);
          if (handle != IntPtr.Zero)
            return this.TreeView.NodeFromHandle(handle);
        }
        return (TreeNode) null;
      }
    }

    [SRDescription("TreeNodeSelectedImageIndexDescr")]
    [Localizable(true)]
    [TypeConverter(typeof (TreeViewImageIndexConverter))]
    [DefaultValue(-1)]
    [RefreshProperties(RefreshProperties.Repaint)]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RelatedImageList("TreeView.ImageList")]
    [SRCategory("CatBehavior")]
    public int SelectedImageIndex
    {
      get
      {
        return this.SelectedImageIndexer.Index;
      }
      set
      {
        this.SelectedImageIndexer.Index = value;
        this.UpdateNode(32);
      }
    }

    [Localizable(true)]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RelatedImageList("TreeView.ImageList")]
    [RefreshProperties(RefreshProperties.Repaint)]
    [SRCategory("CatBehavior")]
    [SRDescription("TreeNodeSelectedImageKeyDescr")]
    [TypeConverter(typeof (TreeViewImageKeyConverter))]
    [DefaultValue("")]
    public string SelectedImageKey
    {
      get
      {
        return this.SelectedImageIndexer.Key;
      }
      set
      {
        this.SelectedImageIndexer.Key = value;
        this.UpdateNode(32);
      }
    }

    internal int State
    {
      get
      {
        if (this.handle == IntPtr.Zero || this.TreeView == null)
          return 0;
        System.Windows.Forms.NativeMethods.TV_ITEM lParam = new System.Windows.Forms.NativeMethods.TV_ITEM();
        lParam.hItem = this.Handle;
        lParam.mask = 24;
        lParam.stateMask = 34;
        System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), System.Windows.Forms.NativeMethods.TVM_GETITEM, 0, ref lParam);
        return lParam.state;
      }
    }

    [TypeConverter(typeof (ImageKeyConverter))]
    [Localizable(true)]
    [SRCategory("CatBehavior")]
    [DefaultValue("")]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RefreshProperties(RefreshProperties.Repaint)]
    [RelatedImageList("TreeView.StateImageList")]
    [SRDescription("TreeNodeStateImageKeyDescr")]
    public string StateImageKey
    {
      get
      {
        return this.StateImageIndexer.Key;
      }
      set
      {
        if (!(this.StateImageIndexer.Key != value))
          return;
        this.StateImageIndexer.Key = value;
        if (this.treeView == null || this.treeView.CheckBoxes)
          return;
        this.UpdateNode(8);
      }
    }

    [SRDescription("TreeNodeStateImageIndexDescr")]
    [DefaultValue(-1)]
    [SRCategory("CatBehavior")]
    [Localizable(true)]
    [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
    [RefreshProperties(RefreshProperties.Repaint)]
    [RelatedImageList("TreeView.StateImageList")]
    [TypeConverter(typeof (NoneExcludedImageIndexConverter))]
    public int StateImageIndex
    {
      get
      {
        if (this.treeView != null && this.treeView.StateImageList != null)
          return this.StateImageIndexer.Index;
        else
          return -1;
      }
      set
      {
        if (value < -1 || value > 14)
        {
          throw new ArgumentOutOfRangeException("StateImageIndex", System.Windows.Forms.SR.GetString("InvalidArgument", (object) "StateImageIndex", (object) value.ToString((IFormatProvider) CultureInfo.CurrentCulture)));
        }
        else
        {
          this.StateImageIndexer.Index = value;
          if (this.treeView == null || this.treeView.CheckBoxes)
            return;
          this.UpdateNode(8);
        }
      }
    }

    [SRCategory("CatData")]
    [Localizable(false)]
    [Bindable(true)]
    [SRDescription("ControlTagDescr")]
    [DefaultValue(null)]
    [TypeConverter(typeof (StringConverter))]
    public object Tag
    {
      get
      {
        return this.userData;
      }
      set
      {
        this.userData = value;
      }
    }

    [Localizable(true)]
    [SRCategory("CatAppearance")]
    [SRDescription("TreeNodeTextDescr")]
    public string Text
    {
      get
      {
        if (this.text != null)
          return this.text;
        else
          return "";
      }
      set
      {
        this.text = value;
        this.UpdateNode(1);
      }
    }

    [SRCategory("CatAppearance")]
    [Localizable(false)]
    [SRDescription("TreeNodeToolTipTextDescr")]
    [DefaultValue("")]
    public string ToolTipText
    {
      get
      {
        return this.toolTipText;
      }
      set
      {
        this.toolTipText = value;
      }
    }

    [SRDescription("TreeNodeNodeNameDescr")]
    [SRCategory("CatAppearance")]
    public string Name
    {
      get
      {
        if (this.name != null)
          return this.name;
        else
          return "";
      }
      set
      {
        this.name = value;
      }
    }

    [Browsable(false)]
    public TreeView TreeView
    {
      get
      {
        if (this.treeView == null)
          this.treeView = this.FindTreeView();
        return this.treeView;
      }
    }

    static TreeNode()
    {
    }

    public TreeNode()
    {
      this.treeNodeState = new BitVector32();
    }

    internal TreeNode(TreeView treeView)
      : this()
    {
      this.treeView = treeView;
    }

    public TreeNode(string text)
      : this()
    {
      this.text = text;
    }

    public TreeNode(string text, TreeNode[] children)
      : this()
    {
      this.text = text;
      this.Nodes.AddRange(children);
    }

    public TreeNode(string text, int imageIndex, int selectedImageIndex)
      : this()
    {
      this.text = text;
      this.ImageIndexer.Index = imageIndex;
      this.SelectedImageIndexer.Index = selectedImageIndex;
    }

    public TreeNode(string text, int imageIndex, int selectedImageIndex, TreeNode[] children)
      : this()
    {
      this.text = text;
      this.ImageIndexer.Index = imageIndex;
      this.SelectedImageIndexer.Index = selectedImageIndex;
      this.Nodes.AddRange(children);
    }

    protected TreeNode(SerializationInfo serializationInfo, StreamingContext context)
      : this()
    {
      this.Deserialize(serializationInfo, context);
    }

    internal int AddSorted(TreeNode node)
    {
      int index1 = 0;
      string text = node.Text;
      TreeView treeView = this.TreeView;
      if (this.childCount > 0)
      {
        if (treeView.TreeViewNodeSorter == null)
        {
          CompareInfo compareInfo = Application.CurrentCulture.CompareInfo;
          if (compareInfo.Compare(this.children[this.childCount - 1].Text, text) <= 0)
          {
            index1 = this.childCount;
          }
          else
          {
            int num1 = 0;
            int num2 = this.childCount;
            while (num1 < num2)
            {
              int index2 = (num1 + num2) / 2;
              if (compareInfo.Compare(this.children[index2].Text, text) <= 0)
                num1 = index2 + 1;
              else
                num2 = index2;
            }
            index1 = num1;
          }
        }
        else
        {
          IComparer treeViewNodeSorter = treeView.TreeViewNodeSorter;
          int num1 = 0;
          int num2 = this.childCount;
          while (num1 < num2)
          {
            int index2 = (num1 + num2) / 2;
            if (treeViewNodeSorter.Compare((object) this.children[index2], (object) node) <= 0)
              num1 = index2 + 1;
            else
              num2 = index2;
          }
          index1 = num1;
        }
      }
      node.SortChildren(treeView);
      this.InsertNodeAt(index1, node);
      return index1;
    }

    public static TreeNode FromHandle(TreeView tree, IntPtr handle)
    {
      System.Windows.Forms.IntSecurity.ControlFromHandleOrLocation.Demand();
      return tree.NodeFromHandle(handle);
    }

    private void SortChildren(TreeView parentTreeView)
    {
      if (this.childCount <= 0)
        return;
      TreeNode[] treeNodeArray = new TreeNode[this.childCount];
      if (parentTreeView == null || parentTreeView.TreeViewNodeSorter == null)
      {
        CompareInfo compareInfo = Application.CurrentCulture.CompareInfo;
        for (int index1 = 0; index1 < this.childCount; ++index1)
        {
          int index2 = -1;
          for (int index3 = 0; index3 < this.childCount; ++index3)
          {
            if (this.children[index3] != null)
            {
              if (index2 == -1)
                index2 = index3;
              else if (compareInfo.Compare(this.children[index3].Text, this.children[index2].Text) <= 0)
                index2 = index3;
            }
          }
          treeNodeArray[index1] = this.children[index2];
          this.children[index2] = (TreeNode) null;
          treeNodeArray[index1].index = index1;
          treeNodeArray[index1].SortChildren(parentTreeView);
        }
        this.children = treeNodeArray;
      }
      else
      {
        IComparer treeViewNodeSorter = parentTreeView.TreeViewNodeSorter;
        for (int index1 = 0; index1 < this.childCount; ++index1)
        {
          int index2 = -1;
          for (int index3 = 0; index3 < this.childCount; ++index3)
          {
            if (this.children[index3] != null)
            {
              if (index2 == -1)
                index2 = index3;
              else if (treeViewNodeSorter.Compare((object) this.children[index3], (object) this.children[index2]) <= 0)
                index2 = index3;
            }
          }
          treeNodeArray[index1] = this.children[index2];
          this.children[index2] = (TreeNode) null;
          treeNodeArray[index1].index = index1;
          treeNodeArray[index1].SortChildren(parentTreeView);
        }
        this.children = treeNodeArray;
      }
    }

    public void BeginEdit()
    {
      if (!(this.handle != IntPtr.Zero))
        return;
      TreeView treeView = this.TreeView;
      if (!treeView.LabelEdit)
        throw new InvalidOperationException(System.Windows.Forms.SR.GetString("TreeNodeBeginEditFailed"));
      if (!treeView.Focused)
        treeView.FocusInternal();
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) treeView, treeView.Handle), System.Windows.Forms.NativeMethods.TVM_EDITLABEL, 0, this.handle);
    }

    internal void Clear()
    {
      bool flag = false;
      TreeView treeView = this.TreeView;
      try
      {
        if (treeView != null)
        {
          treeView.nodesCollectionClear = true;
          if (treeView != null && this.childCount > 200)
          {
            flag = true;
            treeView.BeginUpdate();
          }
        }
        while (this.childCount > 0)
          this.children[this.childCount - 1].Remove(true);
        this.children = (TreeNode[]) null;
        if (treeView == null || !flag)
          return;
        treeView.EndUpdate();
      }
      finally
      {
        if (treeView != null)
          treeView.nodesCollectionClear = false;
        this.nodesCleared = true;
      }
    }

    public virtual object Clone()
    {
      System.Type type = this.GetType();
      TreeNode treeNode = !(type == typeof (TreeNode)) ? (TreeNode) Activator.CreateInstance(type) : new TreeNode(this.text, this.ImageIndexer.Index, this.SelectedImageIndexer.Index);
      treeNode.Text = this.text;
      treeNode.Name = this.name;
      treeNode.ImageIndexer.Index = this.ImageIndexer.Index;
      treeNode.SelectedImageIndexer.Index = this.SelectedImageIndexer.Index;
      treeNode.StateImageIndexer.Index = this.StateImageIndexer.Index;
      treeNode.ToolTipText = this.toolTipText;
      treeNode.ContextMenu = this.contextMenu;
      treeNode.ContextMenuStrip = this.contextMenuStrip;
      if (!string.IsNullOrEmpty(this.ImageIndexer.Key))
        treeNode.ImageIndexer.Key = this.ImageIndexer.Key;
      if (!string.IsNullOrEmpty(this.SelectedImageIndexer.Key))
        treeNode.SelectedImageIndexer.Key = this.SelectedImageIndexer.Key;
      if (!string.IsNullOrEmpty(this.StateImageIndexer.Key))
        treeNode.StateImageIndexer.Key = this.StateImageIndexer.Key;
      if (this.childCount > 0)
      {
        treeNode.children = new TreeNode[this.childCount];
        for (int index = 0; index < this.childCount; ++index)
          treeNode.Nodes.Add((TreeNode) this.children[index].Clone());
      }
      if (this.propBag != null)
        treeNode.propBag = OwnerDrawPropertyBag.Copy(this.propBag);
      treeNode.Checked = this.Checked;
      treeNode.Tag = this.Tag;
      return (object) treeNode;
    }

    private void CollapseInternal(bool ignoreChildren)
    {
      TreeView treeView = this.TreeView;
      bool flag = false;
      this.collapseOnRealization = false;
      this.expandOnRealization = false;
      if (treeView == null || !treeView.IsHandleCreated)
      {
        this.collapseOnRealization = true;
      }
      else
      {
        if (ignoreChildren)
        {
          this.DoCollapse(treeView);
        }
        else
        {
          if (!ignoreChildren && this.childCount > 0)
          {
            for (int index = 0; index < this.childCount; ++index)
            {
              if (treeView.SelectedNode == this.children[index])
                flag = true;
              this.children[index].DoCollapse(treeView);
              this.children[index].Collapse();
            }
          }
          this.DoCollapse(treeView);
        }
        if (flag)
          treeView.SelectedNode = this;
        treeView.Invalidate();
        this.collapseOnRealization = false;
      }
    }

    public void Collapse(bool ignoreChildren)
    {
      this.CollapseInternal(ignoreChildren);
    }

    public void Collapse()
    {
      this.CollapseInternal(false);
    }

    private void DoCollapse(TreeView tv)
    {
      if ((this.State & 32) == 0)
        return;
      TreeViewCancelEventArgs e = new TreeViewCancelEventArgs(this, false, TreeViewAction.Collapse);
      tv.OnBeforeCollapse(e);
      if (e.Cancel)
        return;
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) tv, tv.Handle), 4354, 1, this.Handle);
      tv.OnAfterCollapse(new TreeViewEventArgs(this));
    }

    protected virtual void Deserialize(SerializationInfo serializationInfo, StreamingContext context)
    {
      int length = 0;
      int num1 = -1;
      string str1 = (string) null;
      int num2 = -1;
      string str2 = (string) null;
      int num3 = -1;
      string str3 = (string) null;
      foreach (SerializationEntry serializationEntry in serializationInfo)
      {
        switch (serializationEntry.Name)
        {
          case "PropBag":
            this.propBag = (OwnerDrawPropertyBag) serializationInfo.GetValue(serializationEntry.Name, typeof (OwnerDrawPropertyBag));
            continue;
          case "Text":
            this.Text = serializationInfo.GetString(serializationEntry.Name);
            continue;
          case "Name":
            this.Name = serializationInfo.GetString(serializationEntry.Name);
            continue;
          case "IsChecked":
            this.CheckedStateInternal = serializationInfo.GetBoolean(serializationEntry.Name);
            continue;
          case "ImageIndex":
            num1 = serializationInfo.GetInt32(serializationEntry.Name);
            continue;
          case "SelectedImageIndex":
            num2 = serializationInfo.GetInt32(serializationEntry.Name);
            continue;
          case "ImageKey":
            str1 = serializationInfo.GetString(serializationEntry.Name);
            continue;
          case "SelectedImageKey":
            str2 = serializationInfo.GetString(serializationEntry.Name);
            continue;
          case "StateImageKey":
            str3 = serializationInfo.GetString(serializationEntry.Name);
            continue;
          case "StateImageIndex":
            num3 = serializationInfo.GetInt32(serializationEntry.Name);
            continue;
          case "ChildCount":
            length = serializationInfo.GetInt32(serializationEntry.Name);
            continue;
          case "UserData":
            this.userData = serializationEntry.Value;
            continue;
          default:
            continue;
        }
      }
      if (str1 != null)
        this.ImageKey = str1;
      else if (num1 != -1)
        this.ImageIndex = num1;
      if (str2 != null)
        this.SelectedImageKey = str2;
      else if (num2 != -1)
        this.SelectedImageIndex = num2;
      if (str3 != null)
        this.StateImageKey = str3;
      else if (num3 != -1)
        this.StateImageIndex = num3;
      if (length <= 0)
        return;
      TreeNode[] nodes = new TreeNode[length];
      for (int index = 0; index < length; ++index)
        nodes[index] = (TreeNode) serializationInfo.GetValue("children" + (object) index, typeof (TreeNode));
      this.Nodes.AddRange(nodes);
    }

    public void EndEdit(bool cancel)
    {
      if (this.TreeView == null)
        return;
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4374, cancel ? 1 : 0, 0);
    }

    internal void EnsureCapacity(int num)
    {
      int length1 = num;
      if (length1 < 4)
        length1 = 4;
      if (this.children == null)
      {
        this.children = new TreeNode[length1];
      }
      else
      {
        if (this.childCount + num <= this.children.Length)
          return;
        int length2 = this.childCount + num;
        if (num == 1)
          length2 = this.childCount * 2;
        TreeNode[] treeNodeArray = new TreeNode[length2];
        Array.Copy((Array) this.children, 0, (Array) treeNodeArray, 0, this.childCount);
        this.children = treeNodeArray;
      }
    }

    private void EnsureStateImageValue()
    {
      if (this.treeView == null || !this.treeView.CheckBoxes || this.treeView.StateImageList == null)
        return;
      if (!string.IsNullOrEmpty(this.StateImageKey))
      {
        this.StateImageIndex = this.Checked ? 1 : 0;
        this.StateImageKey = this.treeView.StateImageList.Images.Keys[this.StateImageIndex];
      }
      else
        this.StateImageIndex = this.Checked ? 1 : 0;
    }

    public void EnsureVisible()
    {
      if (this.TreeView == null)
        return;
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4372, 0, this.Handle);
    }

    public void Expand()
    {
      TreeView treeView = this.TreeView;
      if (treeView == null || !treeView.IsHandleCreated)
      {
        this.expandOnRealization = true;
      }
      else
      {
        this.ResetExpandedState(treeView);
        if (!this.IsExpanded)
          System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) treeView, treeView.Handle), 4354, 2, this.Handle);
        this.expandOnRealization = false;
      }
    }

    public void ExpandAll()
    {
      this.Expand();
      for (int index = 0; index < this.childCount; ++index)
        this.children[index].ExpandAll();
    }

    internal TreeView FindTreeView()
    {
      TreeNode treeNode = this;
      while (treeNode.parent != null)
        treeNode = treeNode.parent;
      return treeNode.treeView;
    }

    private void GetFullPath(StringBuilder path, string pathSeparator)
    {
      if (this.parent == null)
        return;
      this.parent.GetFullPath(path, pathSeparator);
      if (this.parent.parent != null)
        path.Append(pathSeparator);
      path.Append(this.text);
    }

    public int GetNodeCount(bool includeSubTrees)
    {
      int num = this.childCount;
      if (includeSubTrees)
      {
        for (int index = 0; index < this.childCount; ++index)
          num += this.children[index].GetNodeCount(true);
      }
      return num;
    }

    internal void InsertNodeAt(int index, TreeNode node)
    {
      this.EnsureCapacity(1);
      node.parent = this;
      node.index = index;
      for (int index1 = this.childCount; index1 > index; --index1)
        (this.children[index1] = this.children[index1 - 1]).index = index1;
      this.children[index] = node;
      ++this.childCount;
      node.Realize(false);
      if (this.TreeView == null || node != this.TreeView.selectedNode)
        return;
      this.TreeView.SelectedNode = node;
    }

    private void InvalidateHostTree()
    {
      if (this.treeView == null || !this.treeView.IsHandleCreated)
        return;
      this.treeView.Invalidate();
    }

    internal void Realize(bool insertFirst)
    {
      TreeView treeView = this.TreeView;
      if (treeView == null || !treeView.IsHandleCreated)
        return;
      if (this.parent != null)
      {
        if (treeView.InvokeRequired)
          throw new InvalidOperationException(System.Windows.Forms.SR.GetString("InvalidCrossThreadControlCall"));
        System.Windows.Forms.NativeMethods.TV_INSERTSTRUCT lParam = new System.Windows.Forms.NativeMethods.TV_INSERTSTRUCT();
        lParam.item_mask = TreeNode.insertMask;
        lParam.hParent = this.parent.handle;
        TreeNode prevNode = this.PrevNode;
        lParam.hInsertAfter = insertFirst || prevNode == null ? (IntPtr) -65535 : prevNode.handle;
        lParam.item_pszText = Marshal.StringToHGlobalAuto(this.text);
        lParam.item_iImage = this.ImageIndexer.ActualIndex == -1 ? treeView.ImageIndexer.ActualIndex : this.ImageIndexer.ActualIndex;
        lParam.item_iSelectedImage = this.SelectedImageIndexer.ActualIndex == -1 ? treeView.SelectedImageIndexer.ActualIndex : this.SelectedImageIndexer.ActualIndex;
        lParam.item_mask = 1;
        lParam.item_stateMask = 0;
        lParam.item_state = 0;
        if (treeView.CheckBoxes)
        {
          lParam.item_mask |= 8;
          lParam.item_stateMask |= 61440;
          lParam.item_state |= this.CheckedInternal ? 8192 : 4096;
        }
        else if (treeView.StateImageList != null && this.StateImageIndexer.ActualIndex >= 0)
        {
          lParam.item_mask |= 8;
          lParam.item_stateMask = 61440;
          lParam.item_state = this.StateImageIndexer.ActualIndex + 1 << 12;
        }
        if (lParam.item_iImage >= 0)
          lParam.item_mask |= 2;
        if (lParam.item_iSelectedImage >= 0)
          lParam.item_mask |= 32;
        bool flag = false;
        if (System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4367, 0, 0) != IntPtr.Zero)
        {
          flag = true;
          System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4374, 0, 0);
        }
        this.handle = System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), System.Windows.Forms.NativeMethods.TVM_INSERTITEM, 0, ref lParam);
        treeView.nodeTable[(object) this.handle] = (object) this;
        this.UpdateNode(4);
        Marshal.FreeHGlobal(lParam.item_pszText);
        if (flag)
          System.Windows.Forms.UnsafeNativeMethods.PostMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), System.Windows.Forms.NativeMethods.TVM_EDITLABEL, IntPtr.Zero, this.handle);
        System.Windows.Forms.SafeNativeMethods.InvalidateRect(new HandleRef((object) treeView, treeView.Handle), (System.Windows.Forms.NativeMethods.COMRECT) null, false);
        if (this.parent.nodesCleared && (insertFirst || prevNode == null) && !treeView.Scrollable)
        {
          System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 11, 1, 0);
          this.nodesCleared = false;
        }
      }
      for (int index = this.childCount - 1; index >= 0; --index)
        this.children[index].Realize(true);
      if (this.expandOnRealization)
        this.Expand();
      if (!this.collapseOnRealization)
        return;
      this.Collapse();
    }

    public void Remove()
    {
      this.Remove(true);
    }

    internal void Remove(bool notify)
    {
      bool isExpanded = this.IsExpanded;
      for (int index = 0; index < this.childCount; ++index)
        this.children[index].Remove(false);
      if (notify && this.parent != null)
      {
        for (int index = this.index; index < this.parent.childCount - 1; ++index)
          (this.parent.children[index] = this.parent.children[index + 1]).index = index;
        this.parent.children[this.parent.childCount - 1] = (TreeNode) null;
        --this.parent.childCount;
        this.parent = (TreeNode) null;
      }
      this.expandOnRealization = isExpanded;
      if (this.TreeView == null)
        return;
      if (this.handle != IntPtr.Zero)
      {
        if (notify && this.TreeView.IsHandleCreated)
          System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), 4353, 0, this.handle);
        this.treeView.nodeTable.Remove((object) this.handle);
        this.handle = IntPtr.Zero;
      }
      this.treeView = (TreeView) null;
    }

    private void RemovePropBagIfEmpty()
    {
      if (this.propBag == null || !this.propBag.IsEmpty())
        return;
      this.propBag = (OwnerDrawPropertyBag) null;
    }

    private void ResetExpandedState(TreeView tv)
    {
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) tv, tv.Handle), System.Windows.Forms.NativeMethods.TVM_SETITEM, 0, ref new System.Windows.Forms.NativeMethods.TV_ITEM()
      {
        mask = 24,
        hItem = this.handle,
        stateMask = 64,
        state = 0
      });
    }

    private bool ShouldSerializeBackColor()
    {
      return this.BackColor != Color.Empty;
    }

    private bool ShouldSerializeForeColor()
    {
      return this.ForeColor != Color.Empty;
    }

    [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)]
    [SecurityPermission(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
    protected virtual void Serialize(SerializationInfo si, StreamingContext context)
    {
      if (this.propBag != null)
        si.AddValue("PropBag", (object) this.propBag, typeof (OwnerDrawPropertyBag));
      si.AddValue("Text", (object) this.text);
      si.AddValue("Name", (object) this.Name);
      si.AddValue("IsChecked", this.treeNodeState[1]);
      si.AddValue("ImageIndex", this.ImageIndexer.Index);
      si.AddValue("ImageKey", (object) this.ImageIndexer.Key);
      si.AddValue("SelectedImageIndex", this.SelectedImageIndexer.Index);
      si.AddValue("SelectedImageKey", (object) this.SelectedImageIndexer.Key);
      if (this.treeView != null && this.treeView.StateImageList != null)
        si.AddValue("StateImageIndex", this.StateImageIndexer.Index);
      if (this.treeView != null && this.treeView.StateImageList != null)
        si.AddValue("StateImageKey", (object) this.StateImageIndexer.Key);
      si.AddValue("ChildCount", this.childCount);
      if (this.childCount > 0)
      {
        for (int index = 0; index < this.childCount; ++index)
          si.AddValue("children" + (object) index, (object) this.children[index], typeof (TreeNode));
      }
      if (this.userData == null || !this.userData.GetType().IsSerializable)
        return;
      si.AddValue("UserData", this.userData, this.userData.GetType());
    }

    public void Toggle()
    {
      if (this.IsExpanded)
        this.Collapse();
      else
        this.Expand();
    }

    public override string ToString()
    {
      return "TreeNode: " + (this.text == null ? "" : this.text);
    }

    private void UpdateNode(int mask)
    {
      if (this.handle == IntPtr.Zero)
        return;
      TreeView treeView = this.TreeView;
      System.Windows.Forms.NativeMethods.TV_ITEM lParam = new System.Windows.Forms.NativeMethods.TV_ITEM();
      lParam.mask = 16 | mask;
      lParam.hItem = this.handle;
      if ((mask & 1) != 0)
        lParam.pszText = Marshal.StringToHGlobalAuto(this.text);
      if ((mask & 2) != 0)
        lParam.iImage = this.ImageIndexer.ActualIndex == -1 ? treeView.ImageIndexer.ActualIndex : this.ImageIndexer.ActualIndex;
      if ((mask & 32) != 0)
        lParam.iSelectedImage = this.SelectedImageIndexer.ActualIndex == -1 ? treeView.SelectedImageIndexer.ActualIndex : this.SelectedImageIndexer.ActualIndex;
      if ((mask & 8) != 0)
      {
        lParam.stateMask = 61440;
        if (this.StateImageIndexer.ActualIndex != -1)
          lParam.state = this.StateImageIndexer.ActualIndex + 1 << 12;
      }
      if ((mask & 4) != 0)
        lParam.lParam = this.handle;
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) treeView, treeView.Handle), System.Windows.Forms.NativeMethods.TVM_SETITEM, 0, ref lParam);
      if ((mask & 1) == 0)
        return;
      Marshal.FreeHGlobal(lParam.pszText);
      if (!treeView.Scrollable)
        return;
      treeView.ForceScrollbarUpdate(false);
    }

    internal void UpdateImage()
    {
      System.Windows.Forms.UnsafeNativeMethods.SendMessage(new HandleRef((object) this.TreeView, this.TreeView.Handle), System.Windows.Forms.NativeMethods.TVM_SETITEM, 0, ref new System.Windows.Forms.NativeMethods.TV_ITEM()
      {
        mask = 18,
        hItem = this.Handle,
        iImage = Math.Max(0, this.ImageIndexer.ActualIndex >= this.TreeView.ImageList.Images.Count ? this.TreeView.ImageList.Images.Count - 1 : this.ImageIndexer.ActualIndex)
      });
    }

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
    void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context)
    {
      this.Serialize(si, context);
    }

    internal class TreeNodeImageIndexer : ImageList.Indexer
    {
      private TreeNode owner;
      private TreeNode.TreeNodeImageIndexer.ImageListType imageListType;

      public override ImageList ImageList
      {
        get
        {
          if (this.owner.TreeView == null)
            return (ImageList) null;
          if (this.imageListType == TreeNode.TreeNodeImageIndexer.ImageListType.State)
            return this.owner.TreeView.StateImageList;
          else
            return this.owner.TreeView.ImageList;
        }
        set
        {
        }
      }

      public TreeNodeImageIndexer(TreeNode node, TreeNode.TreeNodeImageIndexer.ImageListType imageListType)
      {
        this.owner = node;
        this.imageListType = imageListType;
      }

      public enum ImageListType
      {
        Default,
        State,
      }
    }
  }
}
